#include "smallsatos.h"
#include "can_tx.h"
#include "int_eeprom.h"
#include "log.h"
#include "puissance.h"
#include "rtc.h"
#include "storage.h"
#include "dconfig.h"

extern OS_EVENT* carte_experience_lock;
extern INT32U system_time;
extern unsigned char experience_en_cours;
extern unsigned char emission_en_cours;

OS_EVENT* emission_ack_lock;
OS_EVENT* get_emission_ack_lock()
{
	return emission_ack_lock;
}

void incoming(void *pdata)
{
	static INT8U num_mesure = 0;

	INT16U err;
	can_param_t ack;
	can_param_t tcAck;
	can_param_t* message;

	INT16U address;
	INT8U n;

	INT16U ee_ad;
	time_t now;

	evenement_t event;

	eeprom_query query;
	query.type = WRITE_QUERY;
	query.size = 8;

	ack.address = 0x1FF;
	ack.length = 0;

	tcAck.address = 0x2F4;
	tcAck.length = 0;

	emission_ack_lock = OSSemCreate(0);

	for (;;)
	{
		message = (can_param_t*)OSQPend(get_can_incoming_queue(), 0, &err);

		address = message->address;
		switch (address)
		{
			/* Initialisation carte experience */
			case 0x4FE: /* Initialisation experience */
				if (experience_en_cours)
				{
					OSSemPost(get_power_lock());
					OSSemPost(carte_experience_lock);
					experience_en_cours = 0;
				}

				event.code = EV_RESET_EXPERIENCE;
				event.valeur = message->data[0];
				OSQPost(get_event_log_queue(), &event);
				break;
			
			case 0x4F8: /* Mesure dose terminee */
				event.code = EV_FIN_MESURE_DOSE;
				event.valeur = 0;
				OSSemPost(get_power_lock());
				OSSemPost(carte_experience_lock);
				experience_en_cours = 0;
				OSQPost(get_event_log_queue(), &event);
				break;
		
			case 0x47F: /* Initialisation radio */
				if (emission_en_cours)
				{
					OSSemPost(get_power_lock());
					emission_en_cours = 0;
				}

				event.code = EV_RESET_RADIO;
				event.valeur = message->data[0];
				OSQPost(get_event_log_queue(), &event);
				break;
			
			case 0x489: /* Fin emission */
				event.code = EV_FIN_EMISSION;
				event.valeur = 0;
				OSQPost(get_event_log_queue(), &event);
				OSSemPost(get_power_lock());

				emission_en_cours = 0;
				break;
			
			case 0x483: /* TC */
				reconfig(message->data[0], (message->data[1]) + (((message->data[2]) * 256)));
				OSQPost(get_can_outgoing_queue(), &tcAck);
				
				event.code = EV_CONFIG_TIMERS;
				event.valeur = message->data[0];
				OSQPost(get_event_log_queue(), &event);
				break;
			
			case 0x485: /* Valeurs de configuration (controleur) */
				/* Stocker la nouvelle configuration */
				query.size = 8;
				query.address = EE_PARAM_SYS;
				query.value = (INT8U*)message->data;

				OSSemPend(get_eeprom_lock(), 0, &err);
				OSMboxPost(get_eeprom_query_mbox(), &query);
				OSSemPost(get_eeprom_lock());

				event.code = EV_CONFIG_TIMERS;
				event.valeur = 0;
				OSQPost(get_event_log_queue(), &event);
				break;
		
			case 0x440: /* Mise en veille ou reveil */
				event.code = EV_MODE_VEILLE;
				event.valeur = 0;
				OSQPost(get_event_log_queue(), &event);
				break;
			
			case 0x446: /* Antennes bien deployees */
				break;

			case 0x4FF: /* ACK Emission - trame recue */
				OSSemPost(emission_ack_lock);			
				break;

			default:
				/* Traitement resultats mesures */
				if ((address >= 0x401) && (address <= 0x41C))
				{
					/* Resultats experience */
					if (address == 0x401)
					{
						ee_ad = EE_PARAM_EXP + 256*num_mesure;

						OSSemPend(get_rtc_lock(), 0, &err);
						memcpy(&now, &system_time, sizeof(INT32U));
						OSSemPost(get_rtc_lock());

						/* Enregistrer la date */
						query.size = sizeof(time_t);
						query.address = ee_ad + 6;
						query.value = (INT8U*)&now;						

						OSSemPend(get_eeprom_lock(), 0, &err);
						OSMboxPost(get_eeprom_query_mbox(), &query);
						OSSemPost(get_eeprom_lock());

						/* Enregistrer les parametres */
						query.size = 6;
						query.address = ee_ad;
						query.value = message->data;						

						OSSemPend(get_eeprom_lock(), 0, &err);
						OSMboxPost(get_eeprom_query_mbox(), &query);
						OSSemPost(get_eeprom_lock());

						/* ACK */
						OSQPost(get_can_outgoing_queue(), &ack);
					} else {
						/* Resultats de l'experience */

						/* Decoder le numero de la trame */
						if ((address & 0x1) == (!parite(address >> 0x1)))
						{
							/* Parite correcte, on supprime le numero d'ordre et le bit de parite */
							n = ((address - 0x400) >> 1) - 1;
							
							/* Stocker la mesure dans la EEPROM */
							ee_ad = EE_EXPERIENCE + n*8 + 256*num_mesure;
							query.size = 8;
							query.address = ee_ad;
							query.value = message->data;
							
							OSSemPend(get_eeprom_lock(), 0, &err);
							OSMboxPost(get_eeprom_query_mbox(), &query);
							OSSemPost(get_eeprom_lock());						
	
							OSQPost(get_can_outgoing_queue(), &ack);
						}
	
						if (address == 0x41C)
						{
							num_mesure = (num_mesure + 1) % 3; /* On stocke 3 mesures */
	
							/* Enregistrer le numero de la mesure dans la EEPROM */
							query.size = 1;
							query.address = EE_NUM_MESURE;
							query.value = &num_mesure;
							OSSemPend(get_eeprom_lock(), 0, &err);
							OSMboxPost(get_eeprom_query_mbox(), &query);
							OSSemPost(get_eeprom_lock());
	
							experience_en_cours = 0;

							event.code = EV_FIN_MESURES;
							event.valeur = 0;
							OSQPost(get_event_log_queue(), &event);
						}
					}
				} else {
					/* Invalid CAN message */
				}

				/* Fin d'une mesure */
				if (address == 0x41C)
				{	
					OSSemPost(get_power_lock());
					OSSemPost(carte_experience_lock);
				}
		}
		
	}
}	